using System;
using System.Collections.Generic;
using System.Linq;
using System.Management;
using System.Net.NetworkInformation;
using System.Security.Cryptography;
using System.Text;
using System.Windows;
using Microsoft.Win32;

namespace LicenseApp.Client
{
    /// <summary>
    /// 机器码生成器
    /// </summary>
    public class MachineCodeGenerator
    {
        private const string SALT = "LicenseApp2024";
        
        /// <summary>
        /// 生成机器码
        /// </summary>
        /// <returns>格式化的机器码 (XXXX-XXXX-XXXX-XXXX)</returns>
        public static string GenerateMachineCode()
        {
            try
            {
                var components = new List<string>();
                
                // 核心组件（必须有）
                components.Add(GetCpuId());
                components.Add(GetMotherboardSerial());

                // 辅助组件（增强唯一性）
                components.Add(GetSystemDiskSerial());
                //components.Add(GetFirstMacAddress());
                
                // 过滤空值并组合
                var validComponents = components.Where(c => !string.IsNullOrEmpty(c)).ToList();
                
                if (validComponents.Count < 2)
                {
                    // 如果获取的组件太少，使用备用方案
                    return GenerateFallbackMachineCode();
                }
                
                var combined = string.Join("|", validComponents);
                var hash = GenerateHash(combined);
                
                return FormatMachineCode(hash);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"[MachineCodeGenerator] 生成机器码失败: {ex.Message}");
                MessageBox.Show($"{ex.Message} {ex.StackTrace}", "提示");
                return "机器码获取失败";
            }
        }
        
        /// <summary>
        /// 获取CPU序列号
        /// </summary>
        private static string GetCpuId()
        {
            try
            {
                using var searcher = new ManagementObjectSearcher("SELECT ProcessorId FROM Win32_Processor");
                foreach (ManagementObject obj in searcher.Get())
                {
                    var processorId = obj["ProcessorId"]?.ToString();
                    if (!string.IsNullOrEmpty(processorId))
                    {
                        Console.WriteLine($"[MachineCodeGenerator] CPU ID: {processorId}");
                        return processorId;
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"[MachineCodeGenerator] 获取CPU ID失败: {ex.Message}");
            }

            // 备用方案：使用处理器数量和架构
            return $"CPU_{Environment.ProcessorCount}_{Environment.Is64BitOperatingSystem}";
        }


        
        /// <summary>
        /// 获取主板序列号
        /// </summary>
        private static string GetMotherboardSerial()
        {
            try
            {
                using var searcher = new ManagementObjectSearcher("SELECT SerialNumber FROM Win32_BaseBoard");
                foreach (ManagementObject obj in searcher.Get())
                {
                    var serialNumber = obj["SerialNumber"]?.ToString();
                    if (!string.IsNullOrEmpty(serialNumber) && serialNumber != "None")
                    {
                        Console.WriteLine($"[MachineCodeGenerator] 主板序列号: {serialNumber}");
                        return serialNumber;
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"[MachineCodeGenerator] 获取主板序列号失败: {ex.Message}");
            }

            // 备用方案：使用计算机名
            return Environment.MachineName;
        }


        
        /// <summary>
        /// 获取系统盘序列号
        /// </summary>
        private static string GetSystemDiskSerial()
        {
            try
            {
                var systemDrive = Environment.SystemDirectory[0]; // 通常是C:
                using var searcher = new ManagementObjectSearcher($"SELECT SerialNumber FROM Win32_LogicalDisk WHERE DeviceID='{systemDrive}:'");

                foreach (ManagementObject obj in searcher.Get())
                {
                    var serialNumber = obj["SerialNumber"]?.ToString();
                    if (!string.IsNullOrEmpty(serialNumber))
                    {
                        Console.WriteLine($"[MachineCodeGenerator] 系统盘序列号: {serialNumber}");
                        return serialNumber;
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"[MachineCodeGenerator] 获取系统盘序列号失败: {ex.Message}");
            }

            // 备用方案：使用系统盘符
            return Environment.SystemDirectory[0].ToString();
        }


        /// <summary>
        /// 获取第一个网卡MAC地址
        /// </summary>
        private static string GetFirstMacAddress()
        {
            try
            {
                // 获取所有网卡，按MAC地址排序确保稳定性
                var networkInterfaces = NetworkInterface.GetAllNetworkInterfaces()
                    .Where(ni => ni.NetworkInterfaceType != NetworkInterfaceType.Loopback)
                    .Select(ni => new { Interface = ni, Mac = ni.GetPhysicalAddress().ToString() })
                    .Where(x => !string.IsNullOrEmpty(x.Mac) && x.Mac != "000000000000")
                    .OrderBy(x => x.Mac) // 按MAC地址排序，确保稳定性
                    .ToList();

                if (networkInterfaces.Any())
                {
                    var first = networkInterfaces.First();
                    Console.WriteLine($"[MachineCodeGenerator] MAC地址: {first.Mac} (网卡: {first.Interface.Name})");
                    return first.Mac;
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"[MachineCodeGenerator] 获取MAC地址失败: {ex.Message}");
            }
            
            // 备用方案：使用固定标识
            return "MAC_FALLBACK";
        }
        

        
        /// <summary>
        /// 生成备用机器码
        /// </summary>
        private static string GenerateFallbackMachineCode()
        {
            try
            {
                var fallbackComponents = new List<string>
                {
                    Environment.MachineName,
                    Environment.UserName,
                    Environment.ProcessorCount.ToString(),
                    Environment.Is64BitOperatingSystem.ToString(),
                    Environment.SystemDirectory
                };
                
                var combined = string.Join("|", fallbackComponents);
                var hash = GenerateHash(combined);
                
                Console.WriteLine("[MachineCodeGenerator] 使用备用方案生成机器码");
                return FormatMachineCode(hash);
            }
            catch
            {
                // 最后的备用方案
                var emergency = $"{Environment.MachineName}_{DateTime.Now:yyyyMMdd}";
                var hash = GenerateHash(emergency);
                return FormatMachineCode(hash);
            }
        }
        
        /// <summary>
        /// 生成哈希值
        /// </summary>
        private static string GenerateHash(string input)
        {
            var saltedInput = $"{input}|{SALT}";
            using var sha256 = SHA256.Create();
            var hash = sha256.ComputeHash(Encoding.UTF8.GetBytes(saltedInput));
            return Convert.ToBase64String(hash).Replace("+", "").Replace("/", "").Replace("=", "");
        }
        
        /// <summary>
        /// 格式化机器码为 XXXX-XXXX-XXXX-XXXX 格式
        /// </summary>
        private static string FormatMachineCode(string hash)
        {
            // 取前16位字符
            var code = hash.Length >= 16 ? hash[..16] : hash.PadRight(16, '0');
            
            // 格式化为 XXXX-XXXX-XXXX-XXXX
            return $"{code[..4]}-{code[4..8]}-{code[8..12]}-{code[12..16]}".ToUpper();
        }
        
        /// <summary>
        /// 验证机器码是否匹配
        /// </summary>
        /// <param name="storedMachineCode">存储的机器码</param>
        /// <param name="tolerance">容错级别 (0=严格匹配, 1=允许1个组件变化, 2=允许2个组件变化)</param>
        /// <returns>是否匹配</returns>
        public static bool ValidateMachineCode(string storedMachineCode, int tolerance = 1)
        {
            try
            {
                var currentMachineCode = GenerateMachineCode();
                
                Console.WriteLine($"[MachineCodeGenerator] 存储的机器码: {storedMachineCode}");
                Console.WriteLine($"[MachineCodeGenerator] 当前机器码: {currentMachineCode}");
                
                if (storedMachineCode == currentMachineCode)
                {
                    Console.WriteLine("[MachineCodeGenerator] 机器码完全匹配");
                    return true;
                }
                
                if (tolerance > 0)
                {
                    // 容错验证：比较各个组件
                    return ValidateWithTolerance(storedMachineCode, currentMachineCode, tolerance);
                }
                
                Console.WriteLine("[MachineCodeGenerator] 机器码不匹配");
                return false;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"[MachineCodeGenerator] 验证机器码失败: {ex.Message}");
                return false;
            }
        }
        
        /// <summary>
        /// 容错验证机器码
        /// </summary>
        private static bool ValidateWithTolerance(string storedCode, string currentCode, int tolerance)
        {
            try
            {
                // 简单的容错策略：比较字符相似度
                var similarity = CalculateSimilarity(storedCode, currentCode);
                var threshold = tolerance switch
                {
                    1 => 0.75, // 允许25%差异
                    2 => 0.50, // 允许50%差异
                    _ => 0.90  // 默认允许10%差异
                };
                
                var isValid = similarity >= threshold;
                Console.WriteLine($"[MachineCodeGenerator] 机器码相似度: {similarity:P2}, 阈值: {threshold:P2}, 结果: {(isValid ? "通过" : "失败")}");
                
                return isValid;
            }
            catch
            {
                return false;
            }
        }
        
        /// <summary>
        /// 计算两个字符串的相似度
        /// </summary>
        private static double CalculateSimilarity(string str1, string str2)
        {
            if (string.IsNullOrEmpty(str1) || string.IsNullOrEmpty(str2))
                return 0;
            
            var maxLength = Math.Max(str1.Length, str2.Length);
            var matches = 0;
            
            for (int i = 0; i < Math.Min(str1.Length, str2.Length); i++)
            {
                if (str1[i] == str2[i])
                    matches++;
            }
            
            return (double)matches / maxLength;
        }
        
        /// <summary>
        /// 获取机器码组件信息（用于调试）
        /// </summary>
        public static string GetMachineCodeComponents()
        {
            var sb = new StringBuilder();
            sb.AppendLine("=== 机器码组件信息 ===");
            
            try
            {
                sb.AppendLine($"CPU ID: {GetCpuId()}");
                sb.AppendLine($"主板序列号: {GetMotherboardSerial()}");
                sb.AppendLine($"系统盘序列号: {GetSystemDiskSerial()}");
                sb.AppendLine($"MAC地址: {GetFirstMacAddress()}");
                sb.AppendLine($"计算机名: {Environment.MachineName}");
                sb.AppendLine($"用户名: {Environment.UserName}");
                sb.AppendLine($"处理器数量: {Environment.ProcessorCount}");
                sb.AppendLine($"64位系统: {Environment.Is64BitOperatingSystem}");
                
                sb.AppendLine($"\n生成的机器码: {GenerateMachineCode()}");
            }
            catch (Exception ex)
            {
                sb.AppendLine($"获取组件信息失败: {ex.Message}");
            }
            
            return sb.ToString();
        }


    }
}
